/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */
package com.cloud.control.service.socket.codes;

import java.net.InetSocketAddress;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.example.imagine.step1.ImageRequest;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.cloud.control.service.core.ProxyManageServices;
import com.cloud.control.service.socket.entity.ProxyEntity;
import com.cloud.control.service.socket.entity.SenderEntity;
import com.cloud.control.service.socket.entity.SessionMessage;
import com.cloud.control.service.socket.handler.ProxyProtocolHandler;


/**
 * a decoder for {@link ImageRequest} objects
 * 注意: 所有的decode都会调用本class的同一个instance,所以必须避免instance变量引起的冲突!
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */

public class ProxyRequestDecoder extends CumulativeProtocolDecoder {
	/**
	 * 1. 本class是每个session(TCP connection)一个instance
	 * 2. TCP 协议在传送大数据时,底层会自动split data package,我们需要重新把其组装起来
	 * 3.包采用#字符作为结束标志！
	 */
    private final static Log log = LogFactory.getLog(ProxyRequestDecoder.class);
	
    /*
     * 1、doDecode 处理IoSession 和 IoBuffer-> 一个独立的TCP连接（只有一个client！）的buffer！
     * 
     * 2、需要考虑packet粘连的情况，正确的分离出包。 结尾采用#号，便于识别
     * 
     * 3、由于数据是基于socket的，所以不会混淆不同类型的协议，同时，TCP的数据报文是有序的，先发送的报文一定在buff靠前的位置
     * */
    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
    	/**  buff用于完整的接收一个TCP包！**/
       	long current=System.currentTimeMillis();
    	StringBuffer buff=new StringBuffer();
        try {
        	SessionMessage sessionMessage=ProxyManageServices.ioSessionMessages.get(session.toString());
        	if(sessionMessage==null){
        		sessionMessage=new SessionMessage();
        	}
        	sessionMessage.setUpdateTime(current);
        	
        	/** Load本session以前的data！**/
        	buff=sessionMessage.getMessage();
        	
 			int bufLen=in.remaining();
			if(bufLen<=0){
			  return false;    		
			}
			byte[] theMessage=new byte[bufLen];
			String ip = ((InetSocketAddress)session.getRemoteAddress()).getAddress().getHostAddress();
			
			/**把IOBuffer 的数据拷贝到temp缓冲区中！**/
			in.get(theMessage,0,bufLen);
			/**补充代码,2014-09-19  首先应该合并message? **/
			boolean writeFlag=false;

			
			/**逐个byte解析，拼装完整的proxy和sender报文**/
			for(int index=0;index<bufLen;index++){
				String tmp=new String(theMessage,index,1);
				/*第一个字符读取到报文结尾，组装buffer的内容成为一个完整报文！*/
				if(tmp.equals("#")){
					
					/**把已经组装完毕的报文remove, 重新初始化session缓冲区!**/
					sessionMessage.cleanMessageBuffer();
					ProxyManageServices.ioSessionMessages.put(session.toString(), sessionMessage);
					
					log.info("Receive Proxy/Sender's message: " +new String(buff));
				    String[] result = new String(buff).split("----");
				    
				    /**异常报文，报文至少应该包含2个部分！**/
				    if(result==null  || result.length<2 ){
				    	log.error("Abnormal TCP  message: "+new String(buff));
				        writeFlag=true;
				    	break;
				    }
				    
				    /**解析报文头(proxy / sender)**/
				    String packetHeader=result[0];
				    
				    /* 1、代理proxy报文assembly*/
				    if(packetHeader.equalsIgnoreCase("proxy")){
				    	ProxyEntity proxy=new ProxyEntity();
				    	proxy.setSession(session);
				    	proxy.setIpAddress(ip);
				    	proxy.setAllocateTime(current);
				    	
				    	String command=result[1];
				    	if("heartbeat".equals(command)){
				    		proxy.setCommandIn(command);
				    		String port=result[2];
				    		proxy.setPort(port);//代理的端口
				    	}else if("identify".equals(command) && result.length==4){
				    		proxy.setCommandIn(command);
				    		String rsaCert=result[2].replace("#", "");//替换结束字符!
				    		proxy.setRsaCert(rsaCert);
				    		//2014-08-10 identify时发送端口！
				    		String port=result[3].replace("#", "");
				    		proxy.setPort(port);//代理的端口
				    	}else if("register".equals(command)){
				    		proxy.setCommandIn(command);
				    		String userid=result[2].replace("#", "");//替换结束字符!
				    		//中文的用戶名，如：台中|冰晶（用戶）|准銅（負責人）|聯係電話
				    		if(result.length==4){
					    		String name=result[3].replace("#", "");//向下兼容原有的版本，只有2個參數！
					    		proxy.setName(name);
				    		}
				    		proxy.setUserid(userid);
				    	}else{
				    		/**异常报文!**/
					        writeFlag=true;
						    //buff=new StringBuffer();
						    return false;
				    	}
				    	/**提交组装的报文class**/
					    out.write(proxy);
					    /**重新初始化协议缓冲区**/
					    return true;
				    }
				    
				    /*2、sender报文assembly*/
				    String command=result[1];
				    if(packetHeader.equalsIgnoreCase("sender")){
				    	SenderEntity sender=new SenderEntity();
				    	sender.setTaskIP(ip);
				    	
				    	if("heartbeat".equals(command)){
				    		sender.setCommandIn(command);
				    	//证书验证请求
				    	}else if("identify".equals(command) && result.length==3){
				    		sender.setCommandIn(command);
				    		String rsaCert=result[2].replace("#", "");//替换结束字符!
				    		sender.setRsaCert(rsaCert);
				    	//登记证书请求，返回证书！
				    	}else if("register".equals(command)){
				    		sender.setCommandIn(command);
				    		String userid=result[2].replace("#", "");//替换结束字符!
				    		sender.setUserid(userid);
				    		log.error("真相发送程序: "+ip+" 登记到Manager服务器!");
					    //请求代理的报文
				    	}else if("proxies".equals(command) && result.length==4){
				    		sender.setCommandIn(command);
				    		String taskType=result[2];
				    		String count=result[3].replace("#", "");
				    		sender.setTaskLimit(Integer.parseInt(count));
				    		sender.setTaskType(taskType);
				    		log.error("proxies request代理请求 received, 请求类型: "+taskType+"--请求数量:--"+count);    
				    	//获取proxy数量
				    	}else if("pCount".equals(command)){
				    		sender.setCommandIn(command);
				    		log.error("proxies request 获取Manager服务器代理的数量");  
				    	/**增加遠程刪除proxy的能力！  sender----remove----ip#  **/
				    	}else if("remove".equals(command)){
				    		String removedIP=result[2];
				    		sender.setCommandIn(command);
				    		sender.setTaskType(removedIP);
				    		log.error("請求remove idled代理："+ip);   
				    	}else{//异常报文!
						    return false;
				    	}
				    	
					    out.write(sender);
					    return true;
				    }
				}else{ //收到的内容属于同一个协议包，继续缓冲！
					/**更新buffer Hash表的数据**/
					sessionMessage.appendMessage(tmp);
				}
			}//for
			ProxyManageServices.ioSessionMessages.put(session.toString(), sessionMessage);
			
			if(writeFlag){
				return true;
			}
		} catch (Exception e) {
			log.error(e.getCause());
		}
		/**存在其它异常情况**/
    	return false;
    }//doDecode


}
